# Copyright 2021 Huawei Technologies Co., Ltd
#
# Licensed under the BSD 3-Clause License  (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://opensource.org/licenses/BSD-3-Clause
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import os
import math
import numpy as np


def get_l2norm(input_data):
    """计算l2值"""
    sum_data = 0
    for d in input_data:
        sum_data += d * d
    return math.sqrt(sum_data)


def get_dot(array1, array2):
    """获取矩阵乘积"""
    sum_data = 0
    idx = 0
    for data1 in array1:
        data2 = array2[idx]
        sum_data += data1 * data2
        idx += 1
    return sum_data


def get_cosine_smi(data1, data2):
    """获取余弦相似度"""
    n_data1 = get_l2norm(data1)
    n_data2 = get_l2norm(data2)
    return get_dot(data1, data2) / (n_data1 * n_data2)


def get_topK(array1, array2, K=10):
    diff_values = []
    for idx, data1 in enumerate(array1):
        data2 = array2[idx]
        diff_value = abs(data1 - data2)
        diff_values.append(diff_value)
    diff_values = np.array(diff_values)
    topk_index = np.argsort(-diff_values)[:K]
    return array1[topk_index], array2[topk_index]


def get_unormal_values(data1, data2, thre):
    """获取差距过大的异常值"""
    data_sub = abs(data1 - data2)
    unnormal_mask = (data_sub > thre * (abs(data1) + abs(data2)) / 2)
    return data1[unnormal_mask], data2[unnormal_mask]


def get_data(path, dtype=np.float32):
    """加载数据"""
    if path.endswith('.npy'):
        return np.load(path).reshape(-1).astype(np.float32)
    elif path.endswith('.bin'):
        return np.fromfile(path, dtype=dtype).reshape(-1).astype(np.float32)
    else:
        raise NotImplementedError('{} not supported!'.format(os.path.basename(path)))


def main(res_f1, res_f2, thre):
    data1 = get_data(res_f1)
    data2 = get_data(res_f2)
    unnormal_values1, unnormal_values2 = get_unormal_values(data1, data2, thre)
    topK_values1, topK_values2 = get_topK(data1, data2)
    consine_sum = get_cosine_smi(data1, data2)
    print("Unnormal values1:", unnormal_values1)
    print("Unnormal values2:", unnormal_values2)
    print("TopK values1:", topK_values1)
    print("TopK values2:", topK_values2)
    print("Cosine sim:", consine_sum)


if __name__ == '__main__':
    if len(sys.argv) > 3:
        thre = float(sys.argv[3])
    else:
        thre = 0.01
    main(sys.argv[1], sys.argv[2], thre)
